use crate::logger::{parser_log_level_from_u8, Level, LevelFormat, TimeFormat};
use chrono::Local;
use colored::*;
use serde_json::Error;

#[cfg(windows)]
const NEW_LINE: &str = "\r\n";
#[cfg(not(windows))]
const NEW_LINE: &str = "\n";

// 日志实例,每个实例最终组成一个日志行
#[derive(Serialize)]
pub struct Entry {
    pub time: String,         // 日志产生时间
    pub hostname: String,     // 主机名
    pub program_name: String, // 程序名
    pub pid: u32,
    pub level: u8,            // 日志行等级
    pub file: Option<String>, // 文件名称
    pub line: Option<usize>,  // 调用行号
    pub message: String,      //消息体
    with_trace: bool,
}

#[allow(clippy::too_many_arguments)]
impl Entry {
    pub fn new(
        hostname: String,
        program_name: String,
        pid: u32,
        level: u8,
        file: Option<String>,
        line: Option<usize>,
        message: String,
        time_format: TimeFormat,
    ) -> Self {
        Entry {
            time: Self::local_time_now(time_format),
            hostname,
            program_name,
            pid,
            level,
            file,
            line,
            message,
            with_trace: true,
        }
    }
    pub fn new_without_trace(
        hostname: String,
        program_name: String,
        pid: u32,
        level: u8,
        message: String,
        time_format: TimeFormat,
    ) -> Self {
        Entry {
            time: Self::local_time_now(time_format),
            hostname,
            program_name,
            pid,
            level,
            file: None,
            line: None,
            message,
            with_trace: false,
        }
    }
    pub fn format_json(&self) -> Result<Vec<u8>, Error> {
        serde_json::to_vec(self)
    }

    pub fn format_json_pretty(&self) -> Result<Vec<u8>, Error> {
        serde_json::to_vec_pretty(self)
    }

    // 全信息格式化为日志行
    pub fn format_line_all(&self, colored: bool, level_format: LevelFormat) -> Option<Vec<u8>> {
        if self.with_trace {
            let rs = format!(
                "{} {} {}[{}] {} <{}:{}> {}{}",
                self.time,
                self.hostname,
                self.program_name,
                self.pid,
                self.format_colored_level(colored, level_format),
                self.file.to_owned().unwrap_or_default(),
                self.line.unwrap_or(0),
                self.message,
                NEW_LINE
            )
            .into_bytes();
            Some(rs)
        } else {
            let rs = format!(
                "{} {} {}[{}] {} {}{}",
                self.time,
                self.hostname,
                self.program_name,
                self.pid,
                self.format_colored_level(colored, level_format),
                self.message,
                NEW_LINE
            )
            .into_bytes();
            Some(rs)
        }
    }

    // 格式化时间格式，目前仅支持RFC2822 和3339
    fn local_time_now(format: TimeFormat) -> String {
        match format {
            TimeFormat::RFC2822 => Local::now().to_rfc2822(),
            TimeFormat::RFC3339 => Local::now().to_rfc3339(),
        }
    }

    // 格式化颜色并输出
    fn format_colored_level(&self, colored: bool, level_format: LevelFormat) -> String {
        if !colored {
            match level_format {
                LevelFormat::Num => return format!("{}/30", self.level),
                LevelFormat::Letter => {
                    return parser_log_level_from_u8(self.level);
                }
            }
        }
        match level_format {
            LevelFormat::Num => format!("{}/30", self.level),
            LevelFormat::Letter => {
                match self.level.into() {
                    Level::Trace => parser_log_level_from_u8(self.level)
                        .truecolor(143, 143, 143)
                        .to_string(), //灰色
                    Level::Debug => parser_log_level_from_u8(self.level)
                        .truecolor(0, 83, 216)
                        .to_string(), // 蓝色
                    Level::Info => parser_log_level_from_u8(self.level)
                        .truecolor(62, 193, 139)
                        .to_string(), // 绿色
                    Level::Warn => parser_log_level_from_u8(self.level)
                        .truecolor(231, 173, 0)
                        .to_string(), // 橙色
                    Level::Error => parser_log_level_from_u8(self.level)
                        .truecolor(214, 0, 0)
                        .to_string(), // 红色
                    Level::Crit => parser_log_level_from_u8(self.level)
                        .truecolor(192, 0, 0)
                        .to_string(), // 深紫色
                    Level::Fatal => parser_log_level_from_u8(self.level)
                        .truecolor(255, 0, 0)
                        .to_string(), // 深红色
                    Level::Panic => parser_log_level_from_u8(self.level)
                        .truecolor(255, 255, 0)
                        .to_string(), // 深红色
                }
            }
        }
    }
}
